package com.greateamd.timetableasy.server.dao.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.greateamd.timetableasy.client.domain.AuthType;
import com.greateamd.timetableasy.domain.Campus;
import com.greateamd.timetableasy.domain.Event;
import com.greateamd.timetableasy.domain.User;
import com.greateamd.timetableasy.domain.exceptions.IllegalEntityStateException;
import com.greateamd.timetableasy.server.ServerUtil;
import com.greateamd.timetableasy.server.dao.CampusDAO;
import com.greateamd.timetableasy.server.dao.util.AbstractHibernateDAO;



@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, readOnly = false)	
@Repository("campusDAO")
public class CampusDAOImpl extends AbstractHibernateDAO<Campus,Integer> implements CampusDAO {

	public CampusDAOImpl() {
		super(new Campus());
	}

	@Override
	public void save(Campus obj) throws IllegalEntityStateException,HibernateException, SQLException {
		for(User manager : obj.getManagers()){
			if(!manager.containsAuth(AuthType.ROLE_CAMPUS_MANAGER)){
				throw new IllegalEntityStateException("Campus's manger must have \"ROLE_CAMPUS_MANAGER\". "+manager.getUsername()+" doesn't have this right.");
			}
		}
		super.save(obj);
	}
	
	@Override
	public List<Event> getPlanning(final Campus campus, final Date from, final Date to) {
		logger.debug("Get "+campus.getId()+"'s campus planning from db");
		HibernateCallback callback = new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException,SQLException {
				final List<Event> events = new ArrayList<Event>();
				
				//get campus events
				String hql = "SELECT distinct(event) " +
				 "FROM Campus campus " +
				 "JOIN campus.events event " +
				 	"WITH event.startDate >= :from AND event.startDate <= :to "+
			 	 "WHERE campus.id = :campusId " +
				 "ORDER BY event.startDate";
				Query query = session.createQuery(hql);
				query.setParameter("campusId", campus.getId());
				query.setDate("from", from);
				query.setDate("to", to);
				List list = query.list();
				events.addAll(list);
				
				//get campus.university events
				hql = "SELECT distinct(event) " +
				 "FROM Campus campus " +
				 "JOIN campus.university u JOIN u.events event " +
				 	"WITH event.startDate >= :from AND event.startDate <= :to "+
			 	 "WHERE campus.id = :campusId " +
				 "ORDER BY event.startDate";
				query = session.createQuery(hql);
				query.setParameter("campusId", campus.getId());
				query.setDate("from", from);
				query.setDate("to", to);
				list = query.list();
				events.addAll(list);

				ServerUtil.sortStartDateList(events);
				
				return events;
	        }
	    };
	    return (List) getHibernateTemplate().execute(callback);
	}
}